
/*
守护进程
    在程序后台执行的进程 不依赖终端 类似于win中的服务

1、创建子进程，退出父进程。
2、在子进程中调用 setsid() 创建新的会话，使子进程成为新的会话首进程，并脱离终端控制。
3、将当前工作目录更改为根目录，以防止占用挂载点。 chdir()
4、重设文件权限掩码，以避免继承父进程的权限掩码。umask
5、关闭不再需要的文件描述符（如标准输入、输出、错误）。
6、守护进程进入一个无限循环，执行预定的任务。
*/

/*
函数介绍

#include <unistd.h>
pid_t setsid(void);

功能:
    创建一个新会话并使调用进程成为新会话的首领，同时与控制终端分离。

参数:
    无。

返回值:
    成功: 返回新会话的会话 ID。
    失败: 返回 -1，并设置相应的错误码。

====================================================================================

#include <unistd.h>
int chdir(const char *path);

功能:
    改变当前工作目录到指定路径。

参数:
    path: 指向新的工作目录的路径。

返回值:
    成功: 返回 0。
    失败: 返回 -1，并设置相应的错误码。
====================================================================================
*/
#include <head.h>

int main(int argc, char const *argv[])
{
    // 1、创建子进程，退出父进程。
    pid_t pid = 0;

    if (-1 == (pid = fork())) // 创建子进程
    {
        perror("fork error");
        return 0;
    }

    else if (0 < pid) // 退出父进程
    {
        exit(1);
    }

    // 2、创建新会话
    if (-1 == setsid())
    {
        perror("setsid error");
        return 0;
    }

    // 3、将当前工作目录更改为根目录
    if (-1 == chdir("/"))
    {
        perror("chdir error");
        return 0;
    }

    // 4、重设文件权限掩码
    umask(0);

    // 5、关闭文件描述符
    fclose(stdout);
    fclose(stdin);
    fclose(stderr);

    // 6、守护进程任务  写死循环

    while (1)
    {

        FILE *fp = fopen("/tmp/HQYJ.txt", "a"); // a w r
        time_t t1 = time(NULL);
        struct tm *tm_str;

        while (1)
        {
            t1 = time(NULL);         // 获取时间
            tm_str = localtime(&t1); // 计算时间

            fprintf(fp, "HQYJ_log : %2d:%2d:%2d\n",
                    tm_str->tm_hour, tm_str->tm_min, tm_str->tm_sec); // 输出时间
                    fflush(fp);
            sleep(10);                                                // 延时
        }
    }

    return 0;
}
